home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS02.ADF
/
Asm
/
qsort.asm
< prev
next >
Wrap
Assembly Source File
|
1989-05-30
|
9KB
|
297 lines
RORG 0
XDEF _qsort
* The qsort algorithm implemented in 68000 assembler.
* This routine implements the quick sort for any arbitrary data array of
* any arbitrary size. The sort is "in-place" in the array, no temporary
* space is needed aside from a little stack space. I have tried to keep
* this as close to the Unix conventions of qsort as possible. I don't
* think there are any bugs, but who knows.
* Gary Sarff 12/07/85 Compuserve PPN 70167,2216
*
* Calling convention/declaration from Lattice C programs is:
*
* void qsort((char *)base,nel,sizeof (*base),compar)
* unsigned int nel;
* int (*compar)();
*
* base points to the base element of the table to be sorted.
* nel is the number of elements in the table.
* compar is the name of the comparison function, which is called with two
* arguments that point to the elements being compared. The function
* must return an integer less than, equal to, or greater than zero
* according as the first argument is to be considered less than, equal to,
* or greater than the second.
* for example:
* suppose array is declared as:
* struct junk { int xpart;
* int ypart;
* char *message[20];
* } *array[10];
* Then array points to the first of ten identical structures like junk.
* say if we want to sort the array on the xpart then call qsort like:
* qsort((char *)array,10,sizeof(*array),compar);
* you should find sizeof(*array) to be 24 since array is a pointer to
* something of type junk and each thing is 24 bytes long.
*
* Notes: The pointer to the base table should be of type
* pointer-to-element, and cast to type pointer-to-character. The comparison
* function need not compare every byte, so arbitrary data may be contained in
* the elements in addition to the values being compared. In this case only
* compare the xparts of the two values passed (see below).
* Although declared as pointer-to-character, the value returned should be
* cast into type pointer-to-element.
*
* the compar function should be declared as (of course use any name you
* want as long as you pass the name to qsort.)
*
* int compar(first,second)
* and declare first and second as type pointer-to-element. They must be
* declared this way, not as pointer to char or something else, so then you
* can say:
* if (first->xpart < second->xpart) return (-1);
* if (first->xpart == second->xpart) return 0;
* if (first->xpart > second->xpart) return 1;
*
*--------------------------------------------------------------------------
*
_qsort:
link a6,#-4
move.l 20(a6),cmpaddr
move.l 16(a6),nel
move.l 16(a6),(sp)
move.l 12(a6),-(sp)
bsr.l unsgmul * multiply nel by sizeof elements
addq.l #4,sp
add.l 8(a6),d0
move.l d0,(sp)
move.l 8(a6),-(sp)
bsr.s qcont
unlk a6
rts
qcont:
link a6,#-4
movem.l d0/d5-d7/a2/a4-a5,-(sp)
move.l nel,d7
QL0:
move.l 12(a6),d0
sub.l 8(a6),d0
move.l d0,d5
cmp.l d7,d0
bls.l done1
move.l d7,d0
add.l d0,d0
move.l d0,(sp)
move.l d5,-(sp)
bsr.l unsgdiv
addq.l #4,sp
move.l d0,(sp)
move.l d7,-(sp)
bsr.l unsgmul
addq.l #4,sp
move.l d0,d5
move.l 8(a6),d0
add.l d5,d0
movea.l d0,a2
move.l a2,-4(a6)
movea.l 8(a6),a5
move.l 12(a6),d0
sub.l d7,d0
movea.l d0,a4
bra.s compout
comploop:
suba.l d7,a2
move.l a2,(sp)
move.l a5,-(sp)
bsr.l auxfunc
addq.l #4,sp
bra.s compout
complt:
move.l a2,(sp)
move.l a5,-(sp)
movea.l cmpaddr,a0
jsr (a0) * call the user provided compar function
addq.l #4,sp
move.l d0,d6
beq.s comploop
tst.l d6
bge.s compge
QL1: adda.l d7,a5
compout:
cmpa.l a2,a5
bcs.s complt
bra.s compge
move.l a4,(sp)
add.l d7,-4(a6)
move.l -4(a6),-(sp)
bsr.l auxfunc
addq.l #4,sp
bra.s compge
qloop1:
move.l a4,(sp)
add.l d7,-4(a6)
move.l -4(a6),-(sp)
move.l a5,-(sp)
bsr.l qdone
addq.l #8,sp
adda.l d7,a2
movea.l a2,a5
bra.s compge
QL2:
move.l a4,(sp)
move.l -4(a6),-(sp)
movea.l cmpaddr,a0
jsr (a0)
addq.l #4,sp
move.l d0,d6
beq.s compout
tst.l d6
ble.s seege
cmpa.l a2,a5
beq.s qloop1 * see if we have reached end of table
move.l a4,(sp)
move.l a5,-(sp)
bsr.l auxfunc
addq.l #4,sp
suba.l d7,a4
bra.s QL1
seege: suba.l d7,a4
compge:
cmpa.l -4(a6),a4
bhi.s QL2
cmpa.l a2,a5
bne QL3
move.l a2,d0
sub.l 8(a6),d0
move.l 12(a6),d1
sub.l -4(a6),d1
cmp.l d1,d0
blt.s QL4
move.l 12(a6),(sp)
move.l -4(a6),d0
add.l d7,d0
move.l d0,-(sp)
bsr.l qcont * recursive call with partition of table
addq.l #4,sp
move.l a2,12(a6)
bra.l QL0
QL4:
move.l a2,(sp)
move.l 8(a6),-(sp)
bsr.l qcont * recursive call with rest of table.
addq.l #4,sp
move.l -4(a6),d0
add.l d7,d0
move.l d0,8(a6)
bra.l QL0
QL3:
move.l a5,(sp)
suba.l d7,a2
move.l a2,-(sp)
move.l a4,-(sp)
bsr.s qdone
addq.l #8,sp
sub.l d7,-4(a6)
movea.l -4(a6),a4
bra.l compout
done1:
addq.l #4,sp
movem.l (sp)+,a5-a4/a2/d7-d5
unlk a6
rts
auxfunc:
link a6,#0
movem.l d6-d7/a4-a5,-(sp)
move.l nel,d6
movea.l 8(a6),a5
movea.l 12(a6),a4
moveloop:
move.b (a5),d7
move.b (a4),(a5)+
move.b d7,(a4)+
subq.l #1,d6
bne.s moveloop
movem.l (sp)+,a5-a4/d7-d6
unlk a6
rts
qdone:
link a6,#0
movem.l d6-d7/a3-a5,-(sp)
move.l nel,d6
movea.l 8(a6),a5
movea.l 12(a6),a4
movea.l 16(a6),a3
pivloop:
move.b (a5),d0
ext.w d0
ext.l d0
move.l d0,d7
move.b (a3),(a5)+
move.b (a4),(a3)+
move.b d7,(a4)+
subq.l #1,d6
bne.s pivloop
movem.l (sp)+,a5-a3/d7-d6
unlk a6
rts
CNOP 0,4
cmpaddr: DC.L 0
nel: DC.L 0
*
* support routines to do unsigned multiplication and division
*
unsgmul:
lea 4(sp),a0
move.w (a0)+,d0
move.l 8(sp),d1
mulu d1,d0
swap d1
mulu (a0),d1
add.w d1,d0
swap d0
clr.w d0
move.w (a0),d1
mulu 10(sp),d1
add.l d1,d0
move.l d0,-2(a0)
rts
unsgdiv:
lea 4(sp),a0
movem.l d2-d3,-(sp)
move.l (a0),d0
move.l d0,d2
move.l 16(sp),d1
move.l d1,d3
cmpi.l #$10000,d1
bge.s adjust
clr.w d0
swap d0
divu d1,d0
move.w d0,d3
move.w d2,d0
divu d1,d0
swap d0
move.w d3,d0
swap d0
bra.s fini
adjust:
lsr.l #1,d0
lsr.l #1,d1
cmpi.l #$10000,d1
bge.s adjust
divu d1,d0
andi.l #$FFFF,d0
move.l d3,d1
swap d1
mulu d0,d1
swap d1
clr.w d1
mulu d0,d3
add.l d3,d1
cmp.l d1,d2
bge.s fini
subq.l #1,d0
fini:
move.l d0,(a0)
movem.l (sp)+,d3-d2
rts